package clusterpoint

import ("./abbr";
		"strings"; 
		"container/vector");

type ClusterPoint struct {Name string; Val [abbr.StateAbbrLen]bool; Weight int}
//Add an ordering to points
func (p ClusterPoint) Less(y interface{}) bool {
	other := y.(ClusterPoint);
	for i := 0; i < len(p.Val); i++ {
		if p.Val[i] && ! other.Val[i] {
			return false;
		} else if other.Val[i] && !p.Val[i] {
			return true;
		}
	}
	return true;
}
func (p *ClusterPoint) equal(o *ClusterPoint) bool {
	l := len(p.Val);
	if l != len(o.Val) {
		return false;
	}
	for i:= 0; i < l; i++ {
		if p.Val[i] != o.Val[i] {
			return false;
		}
	}
	return true;
}
func (p *ClusterPoint) merge (o *ClusterPoint) {
	p.Name += " " + o.Name;
	p.Weight++;
	return;
}

func (p *ClusterPoint) Dist (o *[]float) float {
	out := 0.0;
	lenI := len(p.Val);
	if lenI!= len(*o) {
		return -1;
	}
	lenF := float(lenI);
	
	for i := 0; i < lenI; i++ {
		val := (*o)[i];
		if p.Val[i] == true {
			val = 1 - val;
		}
		out += val/lenF;
	}
	return out;
}

//Compresses a vector of points by combining equal adjacent elements.
func Compress(init *vector.Vector) *vector.Vector {
	nv := new(vector.Vector);
	var empty ClusterPoint;
	ptr := &empty;
	for v := range init.Iter() {
		vp := v.(ClusterPoint);
		if(!vp.equal(ptr)) {
			ptr = &vp;
			nv.Push(vp);
		} else {
			(*ptr).merge(&vp);
		}
	}
	return nv;
}

//Parse a line of the input file into a point
func ParseLine(input string) ClusterPoint {
	parts := strings.Split(input,",",0);
	var retval ClusterPoint;
	retval.Name = parts[0];
	retval.Weight = 1;
	
	for _,piece := range parts[1:len(parts)] {
		id := abbr.AbbrToInt(piece);
		retval.Val[id] = true;		
	}
	return retval;
}
